iT邦幫忙

2023 iThome 鐵人賽

DAY 14
0
Mobile Development

Ionic結合ChatGPT - 30天打造AI英語口說導師APP系列 第 14

【Day - 14】GPT模型 - 打造流暢自然的英文對話

  • 分享至 

  • xImage
  •  

在昨日的【Day - 13】中,我們對Prompt Engineering有了更深入的理解。今天,我們將運用【Day - 8】所介紹的API,進行實際的串接實作。在接下來的聊天實作部分,我會使用GPT-4作為主要的模型。

準備Model

首先,我們要依照【Day - 8】的介紹,建立相對應的GPT API Model。這樣一來,我們稍後就可以直接使用:

export type ChatRole = 'system' | 'user' | 'assistant';

export interface ChatMessageModel {
  role?: ChatRole;
  name?: string;
  content: string;
}

export interface ChatRequestModel {
  model: string;
  messages: ChatMessageModel[];
  temperature?: number;
  top_p?: number;
  stream?: boolean;
  max_tokens?: number;
}

export interface ChatResponseModel {
  id: string;
  object: string;
  created: number;
  model: string;
  choices: ChatChoicesModel[];
  usage: ChatUsageModel
}

export interface ChatChoicesModel {
  index: number;
  message: ChatMessageModel;
  finish_reason: string;
}

export interface ChatUsageModel {
  prompt_tokens: number;
  completion_tokens: number;
  total_tokens: number;
}

 

建立OpenAI Service

我們建立一個OpenAI Service,在openai.service.ts中注入HttpClient進行API的呼叫。同時,我們也準備了一個陣列來保存所有的歷史對話,並將「System Prompt」加入其中。在呼叫OpenAI的API時,會把語音轉換成的文字和先前的歷史對話合併後傳送API,然後接收來自GPT-4模型的回應。最後,這些回應會被加入到歷史對話陣列中,以便後續能夠持續與GPT-4模型進行上下文相關的對話:

//建立Http header
private headers = new HttpHeaders({
  'Authorization': 'Bearer {你的Token}'
});

private chatMessages: ChatMessageModel[] = [
  {
    role: 'system',
    content: '1.從現在開始你是英文口說導師,所有對話都使用英文。\
              2.你的能力是和學生進行生活一對一會話練習,若學生有不會的單子或句子可以使用中文解釋。\
              3.學生的程度大約落在多益(400-600)分,請你依照這個等級進行問話。\
              4.進行會話練習時,儘可能的導正學生語法上的錯誤。\
              5.你要適時地開啟新的日常話題。'
  },
];

constructor(private http: HttpClient) { }

public chatAPI(contentData: string) {
	//添加使用者訊息
  this.addChatMessage('user', contentData);
  return this.http.post<ChatResponseModel>('https://api.openai.com/v1/chat/completions', this.getConversationRequestData(), { headers: this.headers }).pipe(
    //加入GPT回覆訊息
    tap(chatAPIResult => this.addChatMessage('assistant', chatAPIResult.choices[0].message.content))
  );
}

private getConversationRequestData(): ChatRequestModel {
	return {
		model: 'gpt-4',
		messages: this.chatMessages,
		temperature: 0.7,
		top_p: 1
	}
}

private addChatMessage(roleData: ChatRole, contentData: string) {
  this.chatMessages.push({
    role: roleData,
    content: contentData
  });
}

我們將OpenAI Service注入到Home主頁的home.page.ts後,把chatAPI()方法添加到OnGetRecordingBase64Text()裡面:

//建立Http header
private headers = new HttpHeaders({
  'Authorization': 'Bearer {你的Token}'
});

constructor(private http: HttpClient,
  private statusService: StatusService,
  private openaiService: OpenaiService) { }

OnGetRecordingBase64Text(recordingBase64Data: RecordingData) {
  const requestData: AudioConvertRequestModel = {
    aacBase64Data: recordingBase64Data.value.recordDataBase64
  };
  //啟動讀取
  this.statusService.startLoading();
  //Audio Convert API
  this.http.post<AudioConvertResponseModel>('你的Web APP URL/AudioConvert/aac2m4a', requestData).pipe(
    switchMap(audioAPIResult => {
      //將Base64字串轉為Blob
      const byteCharacters = atob(audioAPIResult.m4aBase64Data);
      const byteNumbers = new Array(byteCharacters.length);
      for (let i = 0; i < byteCharacters.length; i++) {
        byteNumbers[i] = byteCharacters.charCodeAt(i);
      }
      const byteArray = new Uint8Array(byteNumbers);
      const blob = new Blob([byteArray], { type: 'audio/m4a' });
      //建立FormData
      const formData = new FormData();
      formData.append('file', blob, 'audio.m4a');
      formData.append('model', 'whisper-1');
      formData.append('language', 'en');
      //Whisper API
      return this.http.post<WhisperResponseModel>('https://api.openai.com/v1/audio/transcriptions', formData, { headers: this.headers })
    }),
    //Chat API
    switchMap(whisperAPIResult => this.openaiService.chatAPI(whisperAPIResult.text)),
		finalize(() => {
		  //停止讀取
		  this.statusService.stopLoading();
		})
  ).subscribe(result => alert(result.choices[0].message.content));
}

完成以上的程式碼並編譯後,我們嘗試在實體機上對GPT-4模型說:「Hi there!How are you?」,等待API完成後,就可以看到GPT-4模型根據我們的語音給出對應的回答,成功實現了和AI對話的功能。
https://ithelp.ithome.com.tw/upload/images/20230914/201616639s9J0NqWgq.jpg

重構whisperAPI方法

最後,我們將原本的OnGetRecordingBase64Text()方法中的Whisper API呼叫整合到OpenAI Service裡,並且將其命名為whisperAPI()。如此一來,我們就能在同一個地方輕鬆管理和調用所有與OpenAI API相關的功能了:

public whisperAPI(base64Data: string) {
  return this.http.post<WhisperResponseModel>('https://api.openai.com/v1/audio/transcriptions', this.getWhisperFormData(base64Data), { headers: this.headers });
}

private getWhisperFormData(base64Data: string) {
  //將Base64字串轉為Blob
  const byteCharacters = atob(base64Data);
  const byteNumbers = new Array(byteCharacters.length);
  for (let i = 0; i < byteCharacters.length; i++) {
    byteNumbers[i] = byteCharacters.charCodeAt(i);
  }
  const byteArray = new Uint8Array(byteNumbers);
  const blob = new Blob([byteArray], { type: 'audio/m4a' });
  //建立FormData
  const formData = new FormData();
  formData.append('file', blob, 'audio.m4a');
  formData.append('model', 'whisper-1');
  formData.append('language', 'en');
  return formData;
}

這樣OnGetRecordingBase64Text()方法就會變得乾淨許多:

OnGetRecordingBase64Text(recordingBase64Data: RecordingData) {
  const requestData: AudioConvertRequestModel = {
    aacBase64Data: recordingBase64Data.value.recordDataBase64
  };
  //啟動讀取
  this.statusService.startLoading();
  //Audio Convert API
  this.http.post<AudioConvertResponseModel>('你的Web APP URL/AudioConvert/aac2m4a', requestData).pipe(
    //Whisper API
    switchMap(audioAPIResult => this.openaiService.whisperAPI(audioAPIResult.m4aBase64Data)),
    //Chat API
    switchMap(whisperAPIResult => this.openaiService.chatAPI(whisperAPIResult.text)),
    finalize(() => {
      //停止讀取
      this.statusService.stopLoading();
    })
  ).subscribe(result => alert(result.choices[0].message.content));
}

 

結語

今天我們成功將OpenAI的GPT-4模型串接起來,透過GPT語言模型實現了擬真的對話功能。同時,我們也將所有與Whisper API相關的功能集中整合到Service中,使程式碼更加整潔和結構化。



Github專案程式碼:Ionic結合ChatGPT - Day14


上一篇
【Day - 13】Prompt Engineering實戰1 - 測試提示工程
下一篇
【Day - 15】GPT Tokenizer - 計算對話字數
系列文
Ionic結合ChatGPT - 30天打造AI英語口說導師APP30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言